home *** CD-ROM | disk | FTP | other *** search
- #include "stdafx.h"
- #include "glc.h"
- #include <vd2/system/vdalloc.h>
- #include <vd2/Riza/opengl.h>
-
- using namespace GLCIL;
-
- namespace {
- struct RegisterCombinerSrc {
- uint16 mReg;
- uint16 mMapping;
- uint16 mPortion;
-
- void SetZero() {
- mReg = GL_ZERO;
- mMapping = GL_SIGNED_IDENTITY_NV;
- mPortion = GL_RGBA;
- }
-
- void SetOne() {
- mReg = GL_ZERO;
- mMapping = GL_UNSIGNED_INVERT_NV;
- mPortion = GL_RGBA;
- }
-
- void SetMinusOne() {
- mReg = GL_ZERO;
- mMapping = GL_EXPAND_NORMAL_NV;
- mPortion = GL_RGBA;
- }
-
- void Print(uint16 defaultPortion) const {
- const char *s = "zero";
-
- switch(mReg) {
- case GL_SPARE0_NV: s = "r0"; break;
- case GL_SPARE1_NV: s = "r1"; break;
- case GL_PRIMARY_COLOR_NV: s = "v0"; break;
- case GL_SECONDARY_COLOR_NV: s = "v1"; break;
- case GL_TEXTURE0_ARB: s = "t0"; break;
- case GL_TEXTURE1_ARB: s = "t1"; break;
- case GL_TEXTURE2_ARB: s = "t2"; break;
- case GL_TEXTURE3_ARB: s = "t3"; break;
- case GL_CONSTANT_COLOR0_NV: s = "c0"; break;
- case GL_CONSTANT_COLOR1_NV: s = "c1"; break;
- }
-
- switch(mMapping) {
- case GL_UNSIGNED_IDENTITY_NV: printf("%s_sat", s); break;
- case GL_UNSIGNED_INVERT_NV: printf("1-%s", s); break;
- case GL_SIGNED_IDENTITY_NV: printf("%s", s); break;
- case GL_SIGNED_NEGATE_NV: printf("-%s", s); break;
- case GL_EXPAND_NORMAL_NV: printf("%s_bx2", s); break;
- case GL_EXPAND_NEGATE_NV: printf("-%s_bx2", s); break;
- case GL_HALF_BIAS_NORMAL_NV: printf("%s_bias", s); break;
- case GL_HALF_BIAS_NEGATE_NV: printf("-%s_bias", s); break;
- }
-
- if (mPortion != defaultPortion) {
- switch(mPortion) {
- case GL_RGB:
- printf(".rgb");
- break;
- case GL_ALPHA:
- printf(".a");
- break;
- case GL_BLUE:
- printf(".b");
- break;
- }
- }
- }
-
- static uint8 GetRegisterCode(uint16 reg) {
- uint8 code;
-
- switch(reg) {
- case GL_ZERO: code = 0x00; break;
- case GL_DISCARD_NV: code = 0x01; break;
- case GL_SPARE0_NV: code = 0x02; break;
- case GL_SPARE1_NV: code = 0x03; break;
- case GL_PRIMARY_COLOR_NV: code = 0x04; break;
- case GL_SECONDARY_COLOR_NV: code = 0x05; break;
- case GL_CONSTANT_COLOR0_NV: code = 0x06; break;
- case GL_CONSTANT_COLOR1_NV: code = 0x07; break;
- case GL_SPARE0_PLUS_SECONDARY_COLOR_NV: code = 0x08; break;
- case GL_E_TIMES_F_NV: code = 0x09; break;
- case GL_TEXTURE0_ARB: code = 0x0C; break;
- case GL_TEXTURE1_ARB: code = 0x0D; break;
- case GL_TEXTURE2_ARB: code = 0x0E; break;
- case GL_TEXTURE3_ARB: code = 0x0F; break;
- }
-
- return code;
- }
-
- void Write(FILE *f) const {
- uint8 code = GetRegisterCode(mReg);
-
- switch(mMapping) {
- case GL_UNSIGNED_IDENTITY_NV: break;
- case GL_UNSIGNED_INVERT_NV: code |= 0x10; break;
- case GL_SIGNED_IDENTITY_NV: code |= 0x20; break;
- case GL_SIGNED_NEGATE_NV: code |= 0x30; break;
- case GL_EXPAND_NORMAL_NV: code |= 0x40; break;
- case GL_EXPAND_NEGATE_NV: code |= 0x50; break;
- case GL_HALF_BIAS_NORMAL_NV: code |= 0x60; break;
- case GL_HALF_BIAS_NEGATE_NV: code |= 0x70; break;
- }
-
- if (mPortion == GL_ALPHA)
- code |= 0x80;
-
- fprintf(f, "0x%02x", code);
- }
- };
-
- struct RegisterCombinerHalf {
- uint16 mDst[3];
- uint16 mScale;
- uint16 mBias;
- RegisterCombinerSrc mSrc[4];
- bool mbDotAB;
- bool mbDotCD;
- bool mbMux;
-
- RegisterCombinerHalf() {
- mDst[0] = mDst[1] = mDst[2] = GL_DISCARD_NV;
- mScale = GL_NONE;
- mBias = GL_NONE;
- mSrc[0].SetZero();
- mSrc[1].SetZero();
- mSrc[2].SetZero();
- mSrc[3].SetZero();
- mbDotAB = false;
- mbDotCD = false;
- mbMux = false;
- }
-
- void Write(FILE *f) {
- uint8 scaleBiasCode = 0;
-
- if (mBias == GL_BIAS_BY_NEGATIVE_ONE_HALF_NV) {
- if (mScale == GL_SCALE_BY_TWO_NV)
- scaleBiasCode = 5;
- else
- scaleBiasCode = 4;
- } else {
- switch(mScale) {
- case GL_SCALE_BY_TWO_NV:
- scaleBiasCode = 1;
- break;
- case GL_SCALE_BY_FOUR_NV:
- scaleBiasCode = 2;
- break;
- case GL_SCALE_BY_ONE_HALF_NV:
- scaleBiasCode = 3;
- break;
- }
- }
-
- uint8 dst0Code = RegisterCombinerSrc::GetRegisterCode(mDst[0]);
- uint8 dst1Code = RegisterCombinerSrc::GetRegisterCode(mDst[1]);
- uint8 dst2Code = RegisterCombinerSrc::GetRegisterCode(mDst[2]);
-
- fprintf(f, "0x%02x,0x%02x,", scaleBiasCode + (dst0Code << 4), dst1Code + (dst2Code << 4));
- fprintf(f, "0x%02x,", (mbDotAB ? 1 : 0) + (mbDotCD ? 2 : 0) + (mbMux ? 4 : 0));
-
- for(int i=0; i<4; ++i) {
- mSrc[i].Write(f);
- putc(',', f);
- }
- }
- };
-
- struct RegisterCombiner {
- RegisterCombinerHalf mColor;
- RegisterCombinerHalf mAlpha;
- int mConstantMapping[2];
-
- RegisterCombiner() {
- mConstantMapping[0] = -1;
- mConstantMapping[1] = -1;
- }
-
- void Write(FILE *f, bool rc2) {
- if (rc2)
- fprintf(f, "\t0x%02x,0x%02x,", (uint8)mConstantMapping[0], (uint8)mConstantMapping[1]);
- mColor.Write(f);
- mAlpha.Write(f);
- putc('\n', f);
- }
- };
-
- struct RegisterCombinerFinal {
- RegisterCombinerSrc mSrc[7];
- int mConstantMapping[2];
-
- RegisterCombinerFinal() {
- mConstantMapping[0] = -1;
- mConstantMapping[1] = -1;
- mSrc[0].SetZero();
- mSrc[0].mMapping = GL_UNSIGNED_IDENTITY_NV;
- mSrc[1].mReg = GL_SPARE0_NV;
- mSrc[1].mMapping = GL_UNSIGNED_IDENTITY_NV;
- mSrc[1].mPortion = GL_RGB;
- mSrc[2] = mSrc[1];
- mSrc[3].SetZero();
- mSrc[3].mMapping = GL_UNSIGNED_IDENTITY_NV;
- mSrc[4].SetZero();
- mSrc[4].mMapping = GL_UNSIGNED_IDENTITY_NV;
- mSrc[5].SetZero();
- mSrc[5].mMapping = GL_UNSIGNED_IDENTITY_NV;
- mSrc[6].mReg = GL_SPARE0_NV;
- mSrc[6].mMapping = GL_UNSIGNED_IDENTITY_NV;
- mSrc[6].mPortion = GL_ALPHA;
- }
-
- void Write(FILE *f, bool rc2) {
- fputc('\t', f);
- if (rc2)
- fprintf(f, "0x%02x,0x%02x,", (uint8)mConstantMapping[0], (uint8)mConstantMapping[1]);
-
- for(int i=0; i<7; ++i) {
- mSrc[i].Write(f);
- fputc(',', f);
- }
- fputc('\n', f);
- }
- };
-
- class RegisterCombinerConfig : public vdrefcounted<IGLCFragmentShader> {
- public:
- RegisterCombinerConfig()
- : mGeneralCombinerCount(0)
- , mConstantsUsed(0)
- {
- memset(mConstants, 0, sizeof mConstants);
- }
-
- const char *GetTypeString() {
- return mConstantsUsed <= 2 && mGeneralCombinerCount <= 2 ? "kVDOpenGLFragmentShaderModeNVRC" : "kVDOpenGLFragmentShaderModeNVRC2";
- }
-
- void Write(FILE *f, const char *sym) {
- if (mConstantsUsed > 0) {
- fprintf(f, "static const float %s_constants[][4]={\n", sym, mConstantsUsed);
- for(int i=0; i<mConstantsUsed; ++i) {
- fprintf(f, "\t{");
-
- for(int j=0; j<4; ++j) {
- char buf[512];
- sprintf(buf, "%g", mConstants[i][j]);
- if (strchr(buf, '.'))
- fprintf(f, " %sf", buf);
- else
- fprintf(f, " %s.f", buf);
-
- if (j != 3)
- putc(',', f);
- }
-
- fprintf(f, " },\n");
- };
- fprintf(f, "};\n");
- }
-
- bool rc2 = mConstantsUsed > 2 || mGeneralCombinerCount > 2;
- fprintf(f, "static const uint8 %s_bytecode[]={\n", sym);
- for(int i=0; i<mGeneralCombinerCount; ++i)
- mGeneralCombiners[i].Write(f, rc2);
- mFinalCombiner.Write(f, rc2);
- fprintf(f, "};\n");
-
- fprintf(f, "static const struct VDOpenGLNVRegisterCombinerConfig %s={\n", sym);
- fprintf(f, "\t%d, ", mConstantsUsed);
- fprintf(f, "%d, ", mGeneralCombinerCount);
- if (mConstantsUsed > 0)
- fprintf(f, "%s_constants, ", sym);
- else
- fprintf(f, "NULL, ");
- fprintf(f, "%s_bytecode\n", sym);
- fprintf(f, "};\n");
- }
-
- public:
- RegisterCombiner mGeneralCombiners[8];
- RegisterCombinerFinal mFinalCombiner;
- float mConstants[16][4];
- int mConstantsUsed;
- int mGeneralCombinerCount;
- };
- }
-
- IGLCFragmentShader *CompileFragmentShaderNVRegisterCombiners(GLCErrorSink& errout, const GLCFragmentShader& shader, bool NV_register_combiners_2) {
- int combinerLimit = NV_register_combiners_2 ? 8 : 2;
-
- if (!NV_register_combiners_2 && shader.mUsedConstants > 3)
- errout.ThrowError(shader.mLocation, "NV_register_combiners only allows two constant registers");
-
- GLCFragmentShader::FragmentOps::const_iterator it(shader.mOps.begin()), itEnd(shader.mOps.end());
- bool seenFinalCombiner = false;
- int constantStageMask = 0;
- int constantStageCount = 0;
- int combinerOutputMask = 0;
- bool combinerAlphaOp = false;
- bool combinerColorOp = false;
-
- vdautoptr<RegisterCombinerConfig> config(new RegisterCombinerConfig);
- RegisterCombiner *pCombiner = config->mGeneralCombiners;
-
- int constantMapping[16]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
-
- while(it!=itEnd) {
- const GLCFragmentOp& op = *it;
- bool isFinalCombiner = op.mInsn == kFSOpFinal;
-
- if (isFinalCombiner) {
- if (seenFinalCombiner)
- errout.ThrowError(op.mLocation, "Final combiner already configured");
-
- seenFinalCombiner = true;
- } else {
- if (config->mGeneralCombinerCount >= combinerLimit)
- errout.ThrowError(shader.mLocation, "Exceeded instruction count limit for profile (%d max)\n", combinerLimit);
- }
-
- // convert sources
- RegisterCombinerSrc rsrcs[7];
- bool allowAlpha = true;
- bool allowColor = true;
-
- for(int i=0; i<7; ++i) {
- const GLCSourceArg& opsrc = op.mSrcArgs[i];
- RegisterCombinerSrc& rsrc = rsrcs[i];
- int reg = opsrc.mReg;
-
- // map register
- switch(opsrc.mReg & kRegTypeMask) {
- case 0:
- rsrc.mReg = 0;
- break;
- case kRegZero:
- rsrc.mReg = GL_ZERO;
- break;
- case kRegC0:
- {
- int index = reg - kRegC0;
-
- if (constantMapping[index] == -1) {
- constantMapping[index] = config->mConstantsUsed;
- memcpy(config->mConstants[config->mConstantsUsed], shader.mConstants[index], sizeof(float)*4);
- index = config->mConstantsUsed++;
- }
-
- if (NV_register_combiners_2) {
- int *mappings = isFinalCombiner ? config->mFinalCombiner.mConstantMapping : pCombiner->mConstantMapping;
-
- if (index == mappings[0])
- rsrc.mReg = GL_CONSTANT_COLOR0_NV;
- else if (index == mappings[1])
- rsrc.mReg = GL_CONSTANT_COLOR1_NV;
- else if (mappings[0] == -1) {
- mappings[0] = index;
- rsrc.mReg = GL_CONSTANT_COLOR0_NV;
- } else if (mappings[1] == -1) {
- mappings[1] = index;
- rsrc.mReg = GL_CONSTANT_COLOR1_NV;
- } else
- errout.ThrowError(op.mLocation, "Too many constants used in combiner stage (2 max)");
- } else {
- rsrc.mReg = index ? GL_CONSTANT_COLOR1_NV : GL_CONSTANT_COLOR0_NV;
- }
- }
- break;
- case kRegV0:
- if (opsrc.mReg == kRegV0)
- rsrc.mReg = GL_PRIMARY_COLOR_NV;
- else
- rsrc.mReg = GL_SECONDARY_COLOR_NV;
- break;
- case kRegR0:
- if (opsrc.mReg - kRegR0 >= 2)
- errout.ThrowError(op.mLocation, "Invalid spare register (max 2)");
-
- if (opsrc.mReg == kRegR0)
- rsrc.mReg = GL_SPARE0_NV;
- else
- rsrc.mReg = GL_SPARE1_NV;
- break;
-
- case kRegT0:
- if (opsrc.mReg - kRegT0 >= 4)
- errout.ThrowError(op.mLocation, "Invalid spare register (max 2)");
-
- rsrc.mReg = GL_TEXTURE0_ARB + (opsrc.mReg - kRegT0);
- break;
-
- default:
- errout.ThrowError(op.mLocation, "Internal error");
- }
-
- // map swizzle
- if (opsrc.mSwizzle == kSwizzleNone || opsrc.mReg == 0)
- rsrc.mPortion = GL_RGBA;
- else if (opsrc.mSwizzle == kSwizzleRGB && opsrc.mSize == 3) {
- rsrc.mPortion = GL_RGB;
- allowAlpha = false;
- } else if (opsrc.mSwizzle == kSwizzleAlpha)
- rsrc.mPortion = GL_ALPHA;
- else if (opsrc.mSwizzle == kSwizzleBlue) {
- rsrc.mPortion = GL_BLUE;
- allowColor = false;
- } else
- errout.ThrowError(op.mLocation, "Swizzle not allowed in this profile: must be .a, .b, .rgb, or .rgba (none)");
-
- // map modifiers
- switch(opsrc.mMods) {
- case 0:
- rsrc.mMapping = GL_SIGNED_IDENTITY_NV;
- break;
- case kRegModNegate:
- rsrc.mMapping = GL_SIGNED_NEGATE_NV;
- break;
- case kRegModSaturate:
- rsrc.mMapping = GL_UNSIGNED_IDENTITY_NV;
- break;
- case kRegModComplement:
- case kRegModSaturate | kRegModComplement:
- rsrc.mMapping = GL_UNSIGNED_INVERT_NV;
- break;
- case kRegModBias | kRegModX2:
- rsrc.mMapping = GL_EXPAND_NORMAL_NV;
- break;
- case kRegModBias | kRegModX2 | kRegModNegate:
- rsrc.mMapping = GL_EXPAND_NEGATE_NV;
- break;
- case kRegModBias:
- rsrc.mMapping = GL_HALF_BIAS_NORMAL_NV;
- break;
- case kRegModBias | kRegModNegate:
- rsrc.mMapping = GL_HALF_BIAS_NEGATE_NV;
- break;
- default:
- errout.ThrowError(op.mLocation, "Unsupported source modifier");
- break;
- }
- }
-
- if (!isFinalCombiner) {
- // sanity check and convert destinations
- int dstMask = 0;
- uint16 rdsts[3];
-
- for(int dst=0; dst<3; ++dst) {
- int reg = op.mDstArgs[dst].mReg;
-
- rdsts[dst] = GL_DISCARD_NV;
-
- if (reg && reg != kRegDiscard) {
- int regMask = op.mDstArgs[dst].mWriteMask;
- if (!dstMask)
- dstMask = regMask;
- else if (dstMask != regMask)
- errout.ThrowError(op.mLocation, "Inconsistent destination write masks");
-
- switch(reg & kRegTypeMask) {
- case kRegC0:
- errout.ThrowError(op.mLocation, "Constant register cannot be used as destination");
- break;
- case kRegV0:
- errout.ThrowError(op.mLocation, "Interpolator register cannot be used as destination");
- break;
- case kRegT0:
- rdsts[dst] = GL_TEXTURE0_ARB + (reg - kRegT0);
- break;
- case kRegR0:
- if (reg - kRegR0 >= 2)
- errout.ThrowError(op.mLocation, "Invalid spare register (max 2)");
-
- rdsts[dst] = GL_SPARE0_NV + (reg - kRegR0);
- break;
- default:
- errout.ThrowError(op.mLocation, "Invalid destination register");
- }
- }
- }
-
- // assign to color and alpha combiner halves
- bool colorOp = false;
- bool alphaOp = false;
-
- switch(dstMask) {
- case 7:
- colorOp = true;
- break;
- case 8:
- alphaOp = true;
- break;
- case 15:
- alphaOp = true;
- colorOp = true;
- break;
- default:
- errout.ThrowError(op.mLocation, "Invalid destination write mask. Must be one of: .rgb, .a, none (.rgba)");
- }
-
- // convert instruction modifiers
- RegisterCombinerHalf chalf;
-
- switch(op.mModifiers) {
- case 0:
- chalf.mScale = GL_NONE;
- chalf.mBias = GL_NONE;
- break;
- case kInsnModD2:
- chalf.mScale = GL_SCALE_BY_ONE_HALF_NV;
- chalf.mBias = GL_NONE;
- break;
- case kInsnModX2:
- chalf.mScale = GL_SCALE_BY_TWO_NV;
- chalf.mBias = GL_NONE;
- break;
- case kInsnModX4:
- chalf.mScale = GL_SCALE_BY_FOUR_NV;
- chalf.mBias = GL_NONE;
- break;
- case kInsnModBias:
- chalf.mScale = GL_NONE;
- chalf.mBias = GL_BIAS_BY_NEGATIVE_ONE_HALF_NV;
- break;
- case kInsnModBX2:
- chalf.mScale = GL_SCALE_BY_TWO_NV;
- chalf.mBias = GL_BIAS_BY_NEGATIVE_ONE_HALF_NV;
- break;
- default:
- errout.ThrowError(op.mLocation, "Unsupported instruction modifier");
- }
-
- // create combiner configuration
- switch(op.mInsn) {
- case kFSOpMov:
- // A*1 + B*0
- chalf.mDst[0] = rdsts[0];
- chalf.mDst[1] = GL_DISCARD_NV;
- chalf.mDst[2] = GL_DISCARD_NV;
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1].SetOne();
- chalf.mSrc[2].SetZero();
- chalf.mSrc[3].SetZero();
- chalf.mbDotAB = false;
- chalf.mbDotCD = false;
- chalf.mbMux = false;
- break;
- case kFSOpAdd:
- // A*1 + B*1
- chalf.mDst[0] = GL_DISCARD_NV;
- chalf.mDst[1] = GL_DISCARD_NV;
- chalf.mDst[2] = rdsts[0];
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1].SetOne();
- chalf.mSrc[2] = rsrcs[1];
- chalf.mSrc[3].SetOne();
- chalf.mbDotAB = false;
- chalf.mbDotCD = false;
- chalf.mbMux = false;
- break;
- case kFSOpSub:
- // A*1 + B*-1
- chalf.mDst[0] = GL_DISCARD_NV;
- chalf.mDst[1] = GL_DISCARD_NV;
- chalf.mDst[2] = rdsts[0];
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1].SetOne();
- chalf.mSrc[2] = rsrcs[1];
- chalf.mSrc[3].SetMinusOne();
- chalf.mbDotAB = false;
- chalf.mbDotCD = false;
- chalf.mbMux = false;
- break;
- case kFSOpMul:
- // A*B + 0*0
- chalf.mDst[0] = rdsts[0];
- chalf.mDst[1] = GL_DISCARD_NV;
- chalf.mDst[2] = GL_DISCARD_NV;
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1] = rsrcs[1];
- chalf.mSrc[2].SetZero();
- chalf.mSrc[3].SetZero();
- chalf.mbDotAB = false;
- chalf.mbDotCD = false;
- chalf.mbMux = false;
- break;
- case kFSOpMad:
- // A*B + C*0
- chalf.mDst[0] = GL_DISCARD_NV;
- chalf.mDst[1] = GL_DISCARD_NV;
- chalf.mDst[2] = rdsts[0];
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1] = rsrcs[1];
- chalf.mSrc[2] = rsrcs[2];
- chalf.mSrc[3].SetOne();
- chalf.mbDotAB = false;
- chalf.mbDotCD = false;
- chalf.mbMux = false;
- break;
- case kFSOpLrp:
- // A*B + (1-A)*C
- chalf.mDst[0] = GL_DISCARD_NV;
- chalf.mDst[1] = GL_DISCARD_NV;
- chalf.mDst[2] = rdsts[0];
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1] = rsrcs[1];
- chalf.mSrc[2] = rsrcs[0];
- chalf.mSrc[3] = rsrcs[2];
-
- switch(chalf.mSrc[0].mMapping) {
- case GL_UNSIGNED_IDENTITY_NV: // _sat
- case GL_SIGNED_IDENTITY_NV: // (none)
- chalf.mSrc[0].mMapping = GL_UNSIGNED_IDENTITY_NV;
- chalf.mSrc[2].mMapping = GL_UNSIGNED_INVERT_NV;
- break;
-
- case GL_UNSIGNED_INVERT_NV: // 1-reg
- chalf.mSrc[0].mMapping = GL_UNSIGNED_INVERT_NV;
- chalf.mSrc[2].mMapping = GL_UNSIGNED_IDENTITY_NV;
- break;
-
- default:
- errout.ThrowError(op.mLocation, "The first argument to 'lrp' can only use _sat and 1-reg modifiers");
- }
- chalf.mbDotAB = false;
- chalf.mbDotCD = false;
- chalf.mbMux = false;
- break;
- case kFSOpDp3:
- // dot(A.rgb, B.rgb)
- if (alphaOp)
- errout.ThrowError(op.mLocation, "'dp3' cannot be issued as an alpha instruction");
- chalf.mDst[0] = rdsts[0];
- chalf.mDst[1] = GL_DISCARD_NV;
- chalf.mDst[2] = GL_DISCARD_NV;
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1] = rsrcs[1];
- chalf.mSrc[2].SetZero();
- chalf.mSrc[3].SetZero();
- chalf.mbDotAB = true;
- chalf.mbDotCD = false;
- chalf.mbMux = false;
- break;
- case kFSOpMma:
- chalf.mDst[0] = rdsts[0];
- chalf.mDst[1] = rdsts[1];
- chalf.mDst[2] = rdsts[2];
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1] = rsrcs[1];
- chalf.mSrc[2] = rsrcs[2];
- chalf.mSrc[3] = rsrcs[3];
- chalf.mbDotAB = false;
- chalf.mbDotCD = false;
- chalf.mbMux = false;
- break;
- case kFSOpMms:
- chalf.mDst[0] = rdsts[0];
- chalf.mDst[1] = rdsts[1];
- chalf.mDst[2] = rdsts[2];
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1] = rsrcs[1];
- chalf.mSrc[2] = rsrcs[2];
- chalf.mSrc[3] = rsrcs[3];
- chalf.mbDotAB = false;
- chalf.mbDotCD = false;
- chalf.mbMux = true;
- break;
- case kFSOpDm:
- if (alphaOp)
- errout.ThrowError("'dm' cannot be issued as an alpha instruction");
- chalf.mDst[0] = rdsts[0];
- chalf.mDst[1] = rdsts[1];
- chalf.mDst[2] = GL_DISCARD_NV;
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1] = rsrcs[1];
- chalf.mSrc[2] = rsrcs[2];
- chalf.mSrc[3] = rsrcs[3];
- chalf.mbDotAB = true;
- chalf.mbDotCD = false;
- chalf.mbMux = false;
- break;
- case kFSOpDd:
- if (alphaOp)
- errout.ThrowError("'dd' cannot be issued as an alpha instruction");
- chalf.mDst[0] = rdsts[0];
- chalf.mDst[1] = rdsts[1];
- chalf.mDst[2] = GL_DISCARD_NV;
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1] = rsrcs[1];
- chalf.mSrc[2] = rsrcs[2];
- chalf.mSrc[3] = rsrcs[3];
- chalf.mbDotAB = true;
- chalf.mbDotCD = true;
- chalf.mbMux = false;
- break;
- case kFSOpDda:
- if (alphaOp)
- errout.ThrowError("'dda' cannot be issued as an alpha instruction");
- chalf.mDst[0] = rdsts[0];
- chalf.mDst[1] = rdsts[1];
- chalf.mDst[2] = rdsts[2];
- chalf.mSrc[0] = rsrcs[0];
- chalf.mSrc[1] = rsrcs[1];
- chalf.mSrc[2] = rsrcs[2];
- chalf.mSrc[3] = rsrcs[3];
- chalf.mbDotAB = true;
- chalf.mbDotCD = true;
- chalf.mbMux = false;
- break;
- default:
- errout.ThrowError("Instruction not supported in this profile");
- }
-
- if (alphaOp) {
- if (!allowAlpha)
- errout.ThrowError(op.mLocation, "Cannot use RGB argument in alpha operation");
-
- if (combinerAlphaOp)
- errout.ThrowError(op.mLocation, "Cannot co-issue two alpha operations");
-
- combinerAlphaOp = true;
-
- RegisterCombinerHalf& calpha = pCombiner->mAlpha;
- calpha = chalf;
-
- for(int i=0; i<4; ++i) {
- if (calpha.mSrc[i].mPortion == GL_RGBA)
- calpha.mSrc[i].mPortion = GL_ALPHA;
- }
- }
-
- if (colorOp) {
- if (!allowColor)
- errout.ThrowError(op.mLocation, "Cannot use .b swizzle on color operation");
-
- if (combinerColorOp)
- errout.ThrowError(op.mLocation, "Cannot co-issue two color operations");
-
- combinerColorOp = true;
-
- RegisterCombinerHalf& ccolor = pCombiner->mColor;
- ccolor = chalf;
-
- for(int i=0; i<4; ++i) {
- if (ccolor.mSrc[i].mPortion == GL_RGBA)
- ccolor.mSrc[i].mPortion = GL_RGB;
- }
- }
- } else {
- for(int i=0; i<7; ++i) {
- RegisterCombinerSrc& rsrc = config->mFinalCombiner.mSrc[i];
-
- rsrc = rsrcs[i];
-
- switch(rsrc.mMapping) {
- case GL_SIGNED_IDENTITY_NV: // we implicitly saturate, so we allow this
- rsrc.mMapping = GL_UNSIGNED_IDENTITY_NV;
- break;
- case GL_UNSIGNED_IDENTITY_NV:
- case GL_UNSIGNED_INVERT_NV:
- break;
- default:
- errout.ThrowError(op.mLocation, "Inputs to the final combiner must use unsigned saturation or complement");
- break;
- }
-
- if (i < 6) {
- if (rsrc.mPortion == GL_RGBA)
- rsrc.mPortion = GL_RGB;
-
- if (rsrc.mPortion == GL_BLUE)
- errout.ThrowError(op.mLocation, "Final combiner inputs A-F must use .a, .rgb, or .rgba (none) swizzle");
- } else {
- if (rsrc.mPortion == GL_RGB)
- errout.ThrowError(op.mLocation, "Final combiner input G must use .a, .b, or .rgba (none) swizzle");
-
- if (rsrc.mPortion == GL_RGBA)
- rsrc.mPortion = GL_ALPHA;
- }
- }
- }
-
- ++it;
- if (isFinalCombiner || it == itEnd || !it->mbCoIssue) {
- // flush combiner
- if (!isFinalCombiner) {
- ++config->mGeneralCombinerCount;
- ++pCombiner;
- }
-
- constantStageMask = 0;
- constantStageCount = 0;
- combinerAlphaOp = false;
- combinerColorOp = false;
- }
- }
-
- #if 0
- // dump combiners
- for(int i=0; i<config->mConstantsUsed; ++i) {
- printf("def c%d, %g, %g, %g, %g\n", i, config->mConstants[i][0], config->mConstants[i][1], config->mConstants[i][2], config->mConstants[i][3]);
- }
-
- for(int i=0; i<config->mGeneralCombinerCount; ++i) {
- const RegisterCombiner& comb = config->mGeneralCombiners[i];
- int maxdst = 2;
- bool coissue = false;
-
- for(int j=0; j<2; ++j) {
- const RegisterCombinerHalf& chalf = j ? comb.mAlpha : comb.mColor;
-
- if (chalf.mDst[0] == GL_DISCARD_NV && chalf.mDst[1] == GL_DISCARD_NV && chalf.mDst[2] == GL_DISCARD_NV)
- continue;
-
- if (coissue)
- printf("+ ");
- coissue = true;
-
- if (chalf.mbDotAB) {
- if (chalf.mbDotCD)
- printf("dd");
- else
- printf("dm");
- } else {
- if (chalf.mbDotCD)
- printf("md");
- else {
- maxdst = 3;
- if (chalf.mbMux)
- printf("mms");
- else
- printf("mma");
- }
- }
-
- if (chalf.mBias == GL_BIAS_BY_NEGATIVE_ONE_HALF_NV) {
- if (chalf.mScale == GL_SCALE_BY_TWO_NV)
- printf("_bx2");
- else
- printf("_bias");
- } else {
- switch(chalf.mScale) {
- case GL_SCALE_BY_ONE_HALF_NV:
- printf("_d2");
- break;
- case GL_SCALE_BY_TWO_NV:
- printf("_x2");
- break;
- case GL_SCALE_BY_FOUR_NV:
- printf("_x4");
- break;
- }
- }
-
- for(int k=0; k<maxdst; ++k) {
- if (k)
- putchar(',');
-
- putchar(' ');
-
- switch(chalf.mDst[k]) {
- case GL_DISCARD_NV: printf("discard"); break;
- case GL_SPARE0_NV: printf("r0"); break;
- case GL_SPARE1_NV: printf("r1"); break;
- case GL_TEXTURE0_ARB: printf("t0"); break;
- case GL_TEXTURE1_ARB: printf("t1"); break;
- case GL_TEXTURE2_ARB: printf("t2"); break;
- case GL_TEXTURE3_ARB: printf("t3"); break;
- }
-
- if (chalf.mDst[k] != GL_DISCARD_NV)
- printf(j ? ".a" : ".rgb");
- }
-
- for(int k=0; k<4; ++k) {
- const RegisterCombinerSrc& rsrc = chalf.mSrc[k];
-
- printf(", ");
-
- rsrc.Print(j ? GL_ALPHA : GL_RGB);
- }
-
- putchar('\n');
- }
- }
-
- printf("final");
- for(int i=0; i<7; ++i) {
- if (i)
- putchar(',');
- putchar(' ');
- config->mFinalCombiner.mSrc[i].Print(i == 6 ? GL_ALPHA : GL_RGB);
- }
- putchar('\n');
- #endif
-
- return config.release();
- }
-